package org.sgx.dao.util;

import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.sgx.dao.Connectated;
import org.sgx.dao.ConnectionGiver;
import org.sgx.dao.DaoException;
import static org.sgx.dao.util.Util.OMap;
/**
 * sql related utilities. AbstractDao and others are based on this utilities.
 * @author sgurin
 *
 */
public class SQLUtil implements Connectated {

//	public static final String TABLE_NAME_PREFIX = "bee_events_", 
//		TEMPLATE_TABLE_NAME = TABLE_NAME_PREFIX+"Template";
	
	/* sql mappings. the name of these constants are of the java types that this framework supports and will return those java types on queries.*/
	public static final String TYPE_STRING_LONG = "LONGTEXT";
	public static final String TYPE_STRING = "TEXT";
	public static final String TYPE_BOOLEAN = "BOOLEAN";
	public static final String TYPE_DATETIME = "DATETIME";
	public static final String TYPE_LONG = "BIGINT";
	public static final String TYPE_SHORT = "SMALLINT";
	public static final String TYPE_INTEGER = "INTEGER";
	public static final String TYPE_FLOAT = "REAL";
	public static final String TYPE_DOUBLE = "DOUBLE";
	public static final String TYPE_STREAM = "LONGBLOB";
	
	public static String TABLE_PREFIX() {
		return TABLE_PREFIX_;
	}
	private static String TABLE_PREFIX_ = "org_sgx_dao_";
	public static void setTablePrefix(String tablePrefix) {
		if(tablePrefix!=null)
			TABLE_PREFIX_=tablePrefix;
	}
	
	
	public interface SQLObjectBuilder<T> {
		T buildObjectFrom(ResultSet rs) throws Exception;
	}
	private static SQLObjectBuilder<Map> SQLMapBuilder = new SQLObjectBuilder<Map>() {

		public Map buildObjectFrom(ResultSet rs) throws Exception {
			HashMap<Object, Object> m = new HashMap<Object, Object>();
			ResultSetMetaData meta = rs.getMetaData();
			
			for(int i=0; i<meta.getColumnCount(); i++) {
				Object value = rs.getObject(i+1);
				
				//some basic filetering between returned sql types and java types
				/*if(value instanceof java.sql.Date) {
					value = getJavaDate((java.sql.Date) value);
				}
				else if(value instanceof java.sql.Timestamp) {
//					System.out.println("time1: "+date1.getTime());
					value = getJavaDate((java.sql.Timestamp) value);
				}*/
				m.put(meta.getColumnName(i+1), value);
			}
			return m;
		}		
	};
	
	
	
	public SQLUtil(ConnectionGiver connectionGiver) throws DaoException {
		this.connectionGiver=connectionGiver;
		initCounter();
		mapInit();
	}
	
	private ConnectionGiver connectionGiver;
	public static final String I18N_DEFAULT_LOCALE = Locale.US.toString();
	public ConnectionGiver getConnectionGiver() {
		return this.connectionGiver;
	}

	public void setConnectionGiver(ConnectionGiver cg) {
		this.connectionGiver=cg;
	}
	
	

	public static Object getJavaDate(Timestamp t) {
		Date d = new java.util.Date(t.getTime() + (t.getNanos() / 1000000));
		return d;//new Date(t.getTime());
	}
	public static Timestamp getSqlTimestamp(Date d) {
		return new java.sql.Timestamp(d.getTime());
	}
	public static java.sql.Date getSqlDate(Date d) {
		return new java.sql.Date(d.getTime());
	}	
	public static Date getJavaDate(java.sql.Date d) {
		return new Date(d.getTime());
	}
	protected Connection getConnection() throws DaoException {
		return getConnectionGiver().getConnection();//DataAccess.getConnection();
	}
	
		
	public int update(String tableName,
			OrderedMap<Object, Object> matchCols,
			OrderedMap<Object, Object> updateCols) throws DaoException {
		return update(tableName, matchCols, updateCols, null);
	}
	
	public int update(String tableName,
			OrderedMap<Object, Object> matchCols,
			OrderedMap<Object, Object> updateCols, String op) throws DaoException {
		
		op = op==null ? "AND" : op.toUpperCase();
		
		String q = "UPDATE "+tableName+" SET ", 
			where = "";
		
		if(matchCols!=null) {
			where = " WHERE ";
			Iterator<Object> it = matchCols.getOrderedKeys().iterator();
			while(it.hasNext()) {
				where+=it.next()+"=?";
				if(it.hasNext())
					where+=" "+op+" ";
			}
		}
		
		Iterator<Object> it = updateCols.getOrderedKeys().iterator();
		while(it.hasNext()) {
			q += it.next()+"=?";
			if(it.hasNext())
				q += ", ";
		}
		q=q+where;
		try {
			Connection con = getConnection();
			PreparedStatement st = con.prepareStatement(q);
			int counter = 1;
			it = updateCols.getOrderedKeys().iterator();
			while(it.hasNext()) {
				st.setObject(counter, updateCols.get(it.next()));
				counter++;
			}
			if(matchCols!=null) {
				it = matchCols.getOrderedKeys().iterator();
				while(it.hasNext()) {
					st.setObject(counter, matchCols.get(it.next()));
					counter++;
				}
			}
			int ret = st.executeUpdate();
			sqlClose(st, con);
//			st.close();
			return ret;
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}
	
	public void sqlClose(ResultSet rs) throws DaoException {
		sqlClose(rs, null, null);
	}
	public void sqlClose(Statement st, Connection con) throws DaoException {
		sqlClose(null, st, con);
	}
	public void sqlClose(ResultSet rs, Connection con) throws DaoException {
		sqlClose(rs, null, con);
	}
	public void sqlClose(ResultSet rs, Statement st, Connection con) throws DaoException {
		try {
			if(rs!=null)
				try {rs.close();}catch (Exception e) {	}
			if(st!=null)
				try {st.close();}catch (Exception e) {	}
			if(con!=null && getConnectionGiver().connectionMustClose()) {
//				System.out.println("CONNECTION CLOSED "+con);
				con.close();
			}
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}
	public int delete(String tableName, OrderedMap<Object, Object> matchCols) throws DaoException {
		return delete(tableName, matchCols, null);
	}
	public int delete(String tableName, OrderedMap<Object, Object> matchCols, String op) throws DaoException {
		String q = "DELETE FROM "+tableName+" WHERE ";
		op = op==null?"AND":op.toUpperCase();
		Iterator<Object> it = matchCols.getOrderedKeys().iterator();
		while(it.hasNext()) {
			q+=it.next()+"=?";
			if(it.hasNext())
				q+=" "+op+" ";
		}
		try {
			Connection con = getConnection();
			PreparedStatement st = con.prepareStatement(q);
			int counter = 1;
			
			it = matchCols.getOrderedKeys().iterator();
			while(it.hasNext()) {
				st.setObject(counter, matchCols.get(it.next()));
				counter++;
			}
			int ret = st.executeUpdate();
//			st.close();
			sqlClose(st, con);
			return ret;
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}
	
	/* *** clob - bynary stream in java helpers *** */
	public List<byte[]> readBlobs(String tableName, OrderedMap<Object, Object> matchCols, final String colName) throws DaoException {
//		Connection con = getConnection();
		try {
			return query(tableName, matchCols, null, new SQLObjectBuilder<byte[]>(){
				public byte[] buildObjectFrom(ResultSet rs) throws Exception {
					Blob blob = rs.getBlob(colName);
					return Util.toByteArray(blob.getBinaryStream());
				}
			});
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}
	/**
	 * update a sql entry blob field.
	 * @param tableName
	 * @param colName
	 * @param data
	 * @throws DaoException 
	 */
	public void writeBlob(String tableName, OrderedMap<Object, Object> matchCols, String colName, byte[] data) throws DaoException {
		update(tableName, matchCols, Util.<Object>toOrderedMap(colName, data));
	}
	
	public List<Map> query(String tableName, OrderedMap<Object, Object> matchCols) throws DaoException {
		return query(tableName, matchCols, null, null);
	}
	public List<Map> query(String tableName, OrderedMap<Object, Object> matchCols, String op) throws DaoException {
		return query(tableName, matchCols, op, null);
	}
	public <T> List<T> query(String tableName, OrderedMap<Object, Object> matchCols, 
			String op, SQLObjectBuilder<T> builder) throws DaoException {
		builder = (SQLObjectBuilder<T>) (builder==null ? SQLMapBuilder : builder);
		op = op==null ? "AND" : op.toUpperCase();
		String q = "SELECT * FROM "+tableName+" WHERE ";
		
		Iterator<Object> it = matchCols.getOrderedKeys().iterator();
		while(it.hasNext()) {
			q+=it.next()+"=?";
			if(it.hasNext())
				q+=" "+op+" ";
		}
		try {
			Connection con = getConnection();
			PreparedStatement st = con.prepareStatement(q);
			int counter = 1;
			
			it = matchCols.getOrderedKeys().iterator();
			while(it.hasNext()) {
				st.setObject(counter, matchCols.get(it.next()));
				counter++;
			}
			List<T> l = new LinkedList<T>();
			ResultSet rs = st.executeQuery();
			
			while (rs.next()) {
				l.add(builder.buildObjectFrom(rs));
			}
			sqlClose(rs, st, con);
//			rs.close();
			return l;
		} catch (Exception e) {
			throw new DaoException(e);
		}
		
		
	}
	
	
	/** it will return the first matched entry in a table column. will use SQLMapBuilder for 
	 * building the java object that represents the entry. So the object returned will be a map which keys correspond o sql column names of the indicated table.
	 * @param tableName
	 * @param columnName
	 * @param value the value to match in the columnName
	 *  @return null if entry is not found 
	 */
	public Map queryOne(String tableName, String columnName, 
			Object value) throws DaoException {
		return (Map) queryOne(tableName, columnName, value, SQLMapBuilder);
	}
			
	/**
	 * it will retturn the first matched entry in a table column
	 * @param <T>
	 * @param tableName
	 * @param columnName
	 * @param value
	 * @param builder the object to use for building java objects from a sql result set
	 * @return null if entry is not found 
	 * @throws DaoException
	 */
	public <T> T queryOne(String tableName, String columnName, 
			Object value, SQLObjectBuilder<T> builder) throws DaoException {	
//		if(!tableExists(tableName))
//			return null;
		try {
		Connection con = getConnection();
		
//		Statement st = con.createStatement();
//		ResultSet rset = st.executeQuery("SELECT * FROM " + tableName + " WHERE " + columnName + "=" + quotedValue);
		
		String q = "SELECT * FROM " + tableName + " WHERE " + columnName + "=?";
		PreparedStatement st = con.prepareStatement(q);
		st.setObject(1, value);
		ResultSet rset = st.executeQuery();
			
		while (rset.next()) {
			T o = builder.buildObjectFrom(rset);
			sqlClose(rset, st, con);
			return o;
		}
		sqlClose(rset, st, con);
		return null;
		} catch(Exception e) {
			throw new DaoException(e);
		}
	}

	public <T> List<T> queryAll(String tableName, SQLObjectBuilder<T> builder) throws DaoException {
		List<T> l = new LinkedList<T>();
		try {
			Connection con = getConnection();
			Statement st = con.createStatement();
			ResultSet rset = st.executeQuery("SELECT * FROM " + tableName);		
			
			while (rset.next()) {
				l.add(builder.buildObjectFrom(rset));
			}
			sqlClose(rset, st, con);
			return l;
		} catch(Exception e) {
			throw new DaoException(e);
		}
	}
	
	/** it will return the all rows in a table in the form of a list of java map Objects.  
	 * It will use SQLMapBuilder for 
	 * building the java object that represents the entry, so the object returned will be a map which keys correspond o sql column names of the indicated table.
	 * @param tableName
	 * @return
	 * @throws DaoException
	 */
	public List<Map>  queryAll(String tableName) throws DaoException {
		return (List<Map>) queryAll(tableName, SQLMapBuilder);
	}
	
	
	public boolean insert(Map<?,?> fields, String tableName) throws DaoException  {
		try {
		Connection conn = getConnection();
		String st = "insert into "+tableName+"(", 
			stend = ") values (";
		
		Iterator<?> fi = fields.keySet().iterator();
		while(fi.hasNext()) {
			String f = fi.next()+"";
			st+=f;
			stend+="?";
			if(fi.hasNext()) {
				st+=",";
				stend+=",";
			}
		}
		st+=stend+")";
		PreparedStatement pst = conn.prepareStatement(st);
		int i=1;
		fi = fields.keySet().iterator();
		while(fi.hasNext()) {
			pst.setObject(i, fields.get(fi.next()));//pst.setString(i, fields.get(fi.next()));
			i++;
		}
		boolean ret = pst.execute();
		sqlClose(pst, conn);
//		pst.close();
//		conn.close();
		return ret;
		} catch(Exception e) {
			throw new DaoException(e);
		}
	}
	
	
	
	
	
	
	
	
	
	
	
	/* ** table operations ** */
	

	public void tableCreate(String tableName, OrderedMap<String, String> tableCols) 
	throws DaoException {
		try {
		Connection con = getConnection();
		
		String s;
		s = "create table "+tableName+" (";
		
		Iterator<String> it = tableCols.getOrderedKeys().iterator();
		while(it.hasNext()) {
			String cname = it.next();
			s += cname + " " + tableCols.get(cname);
			if(it.hasNext())
				s += ", ";
		}
		s+=")";
//		System.out.println(s);
		Statement stmt = con.createStatement();
   		stmt.executeUpdate(s);
   		sqlClose(stmt, con);
//		stmt.close();
//		con.close();
		} catch(Exception e) {
			throw new DaoException(e);
		}
	}
	public void tableDrop(String tableName) throws DaoException {
		try {
			Connection con = getConnection();
			Statement stmt = con.createStatement();
	   		stmt.executeUpdate("DROP TABLE "+tableName);
	   		sqlClose(stmt, con);
		} catch(Exception e) {
			throw new DaoException(e);
		}
	}
	public void tableDropAll() throws DaoException {
		List<String> allTables = new LinkedList<String>();
		Connection con = getConnection();
		try {
			Statement st = con.createStatement();
			ResultSet rs = st.executeQuery("show tables");
			while(rs.next()) {
				allTables.add(rs.getObject(1)+"");
			}
			sqlClose(rs, st, con);
			
			for(String t : allTables) {
				tableDrop(t);
			}
		}catch (Exception e) {
			throw new DaoException(e);
		}
	}
	public String dump(ResultSet res) throws SQLException {
		ResultSetMetaData md = res.getMetaData();
		StringBuilder sb = new StringBuilder();
		while (res.next()) {
			int ccount = md.getColumnCount();
			for (int i = 0; i < md.getColumnCount(); i++) {
				sb.append(res.getObject(i+1) + "\t\t");
			}
			sb.append("\n");
		}
		return sb.toString();
	}
	public boolean tableExists(String tableName) throws DaoException {
		try {
		Connection con = getConnection();
		DatabaseMetaData dbm = con.getMetaData();
		ResultSet rs = dbm.getTables(null, null, tableName, null);		
		boolean ret = false;
		if (rs.next()) {
			return true;
		}
		sqlClose(rs, con);
		return ret;
		} catch(Exception e) {
			throw new DaoException(e);
		}
	}
	/**
	 * @param tableName
	 * @return a column name -> sql.Type id map
	 * @throws DaoException
	 */
	public Map<String, Integer> tableGetColumns(String tableName)
			throws DaoException {
		Connection con = getConnection();
		try {
			Map<String, Integer> m = new HashMap<String, Integer>();
			Statement st = con.createStatement();
			ResultSet rs = st.executeQuery("SELECT * FROM "+tableName);
			ResultSetMetaData md = rs.getMetaData();
			for (int i = 1; i <= md.getColumnCount(); i++) {
				m.put(md.getColumnName(i), md.getColumnType(i));
			}
			sqlClose(rs, st, con);
			return m;
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}
	public boolean tableHasColumn(String tableName, String colName) throws DaoException {
		return tableGetColumns(tableName).containsKey(colName);
	}
	public int tableAddColumn(String tableName, String colName, String type) throws DaoException {
		Connection con = getConnection();
		try {
			Statement st = con.createStatement();
			int n = st.executeUpdate("ALTER TABLE "+tableName+" ADD "+colName+" "+type);			
			sqlClose(st, con);
			return n;
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}	
	public int tableDropColumn(String tableName, String colName) throws DaoException {
		Connection con = getConnection();
		try {
			Statement st = con.createStatement();
			int n = st.executeUpdate("ALTER TABLE "+tableName+" DROP COLUMN "+colName);			
			sqlClose(st, con);
			return n;
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}
	
	

	
	
	
	
	
	
	
	
	/* *** search basic utilities *** */
	
	
	public static interface StringMatcher {		
		boolean match(String keyword, Object value);
	}
	public static StringMatcher defaultStringMatcher = new StringMatcher(){
		public boolean match(String keyword, Object value) {
			return value==null ? false : value.toString().contains(keyword); 
		}	
	};
	
	/**
	 * Note: this is a very heavy operation for searching. it doesn't use any indexes, so use only with small data sets.
	 * @param tableName
	 * @param idColName - the column name of the Long ids of the table. This ids will be returned
	 * @param matchCols - columns for doing the first query which results will be searched. If null, all entries will be searched.
	 * @param keywords - a map columnname->keyword
	 * @param matcher - optional
	 * @param operator - optional, can be "and" or "or"
	 * @return the ids of matched elements
	 * @throws DaoException
	 */
	public List<Long> search(String tableName, String idColName, OrderedMap<Object, Object> matchCols, 
			OrderedMap<String, String> keywords, StringMatcher matcher, String operator) throws DaoException {
		operator=operator==null?"and":operator;
		List<Map> all = null;
		if(matchCols!=null) {
			all = query(tableName, matchCols);
		}
		else {
			all = queryAll(tableName);
		}
		
		List<Long> l = new LinkedList<Long>();
		for(Map m : all) {
			if(match(m, keywords, matcher, operator.toLowerCase()))
				l.add(Long.parseLong(m.get(idColName)+""));
		}
		return l;
	}
	public List<Long> search(String tableName, String idColName, OrderedMap<String, String> keywords, 
			StringMatcher matcher, String operator) throws DaoException {
		return search(tableName, idColName, null, keywords, matcher, operator);
	}
	public List<Long> search(String tableName, String idColName, OrderedMap<String, String> keywords) throws DaoException {
		return search(tableName, idColName, keywords, defaultStringMatcher, null);
	}
	private boolean match(Map m, OrderedMap<String, String> keywords, StringMatcher matcher, String operator) {
		if(operator.equals("or"))
			return matchOr(m, keywords, matcher);
		else
			return matchAnd(m, keywords, matcher);
	}
	private boolean matchAnd(Map m, OrderedMap<String, String> keywords,
			StringMatcher matcher) {
		for(String colName : keywords.keySet()) {
			if(!matcher.match(keywords.get(colName), m.get(colName)))
				return false;
		}
		return true;
	}
	private boolean matchOr(Map m, OrderedMap<String, String> keywords,
			StringMatcher matcher) {		
		for(String colName : keywords.keySet()) {
			boolean match = matcher.match(keywords.get(colName), m.get(colName));
//			System.out.println("OR: "+keywords.get(colName)+", "+m.get(colName)+" : "+match);
			if(match)
				return true;
		}
		return false;
	}
	
	
	
	
	
	
	
	

	
	/* *** dynamic utilities : using sql tables, the following define method utilities for doing persistent task 
	 * needed by connectiongivers implementations, like incrementing counter, db map objects, etc. *** */
		

	private static final String COUNTER_TABLE_COLUMN_CLASSID = "classId",
		COUNTER_TABLE_COLUMN_COUNTER = "counter";
	private static final long COUNTER_START_COUNT = 1l;
	private static String COUNTER_TABLE_NAME() {
		return TABLE_PREFIX()+"counter";	
	}
	
	public long incrementCounter(String classId) throws DaoException {
		initCounter();
		Map r = this.queryOne(COUNTER_TABLE_NAME(), COUNTER_TABLE_COLUMN_CLASSID, classId);
		if(r==null) { /* there is no row for the class */
			this.insert(OMap(
				COUNTER_TABLE_COLUMN_CLASSID, classId, 
				COUNTER_TABLE_COLUMN_COUNTER, COUNTER_START_COUNT
			), COUNTER_TABLE_NAME());
			return COUNTER_START_COUNT;
		}
		else {
			Long c = (Long) r.get(COUNTER_TABLE_COLUMN_COUNTER);
			this.update(COUNTER_TABLE_NAME(), 
				OMap(COUNTER_TABLE_COLUMN_CLASSID, classId), 
				OMap(COUNTER_TABLE_COLUMN_COUNTER, c.longValue()+1));
			return c.longValue()+1;
		}
	}
	private void initCounter() throws DaoException {
		try {
			if(!this.tableExists(COUNTER_TABLE_NAME())) {
				this.tableCreate(COUNTER_TABLE_NAME(), Util.toOrderedMap(
					COUNTER_TABLE_COLUMN_CLASSID, TYPE_STRING, 
					COUNTER_TABLE_COLUMN_COUNTER, TYPE_LONG
				));
			}
		} catch (Exception e) {
			throw new DaoException(e);
		}		
	}
	
	//a string map utility
	private static final String /*MAP_TABLE_NAME = TABLE_PREFIX+"stringmap", */
		MAP_TABLE_COLUMN_NAME="mapName", 
		MAP_TABLE_COLUMN_KEY="mapKey",
		MAP_TABLE_COLUMN_VALUE="mapVal";
	
	private static String MAP_TABLE_NAME() {
		return TABLE_PREFIX()+"stringmap";
	}
	public void mapPut(String name, String k, String v) throws DaoException {
//		Map r = this.queryOne(MAP_TABLE_NAME, MAP_TABLE_COLUMN_KEY, k);
		List<Map> q = query(MAP_TABLE_NAME(), OMap(
			MAP_TABLE_COLUMN_NAME, name,
			MAP_TABLE_COLUMN_KEY, k)
		);
		if(q.size()==0) { /* not exists */
			insert(
				OMap(	MAP_TABLE_COLUMN_NAME, name,
						MAP_TABLE_COLUMN_KEY, k, 
						MAP_TABLE_COLUMN_VALUE, v
			), MAP_TABLE_NAME());
		}
		else {
//			Long c = (Long) r.get(COUNTER_TABLE_COLUMN_COUNTER);
			update(MAP_TABLE_NAME(), 
				OMap(	MAP_TABLE_COLUMN_NAME, name, 
						MAP_TABLE_COLUMN_KEY, k), 
				OMap(	MAP_TABLE_COLUMN_VALUE, v)
			);
		}
	}
	public String mapGet(String name, String k) throws DaoException {
		List<Map> q = query(MAP_TABLE_NAME(), OMap(
			MAP_TABLE_COLUMN_NAME, name,
			MAP_TABLE_COLUMN_KEY, k)
		);
		if(q.size()==0)
			return null;
		else{
			return (String) q.get(0).get(MAP_TABLE_COLUMN_VALUE);
		}
//		Map r = this.queryOne(MAP_TABLE_NAME, MAP_TABLE_COLUMN_KEY, k);
//		return (String) (r==null?null:r.get(MAP_TABLE_COLUMN_VALUE));
	}
//	public String mapGetKey(String v) throws DaoException  {
//		Map r = this.queryOne(MAP_TABLE_NAME, MAP_TABLE_COLUMN_VALUE, v);
//		return (String) (r==null?null:r.get(MAP_TABLE_COLUMN_KEY));
//	}
	public String mapRemoveKey(String name, String k) throws DaoException  {
		List<Map> q = query(MAP_TABLE_NAME(), OMap(
			MAP_TABLE_COLUMN_NAME, name,
			MAP_TABLE_COLUMN_KEY, k)
		);
		if(q.size()==0)
			return null;
		else{
			delete(MAP_TABLE_NAME(), OMap(
				MAP_TABLE_COLUMN_NAME, name,
				MAP_TABLE_COLUMN_KEY, k));
			return (String) q.get(0).get(MAP_TABLE_COLUMN_VALUE);
//			return (String) q.get(0).get(MAP_TABLE_COLUMN_VALUE);
		}
	}
//	public boolean mapRemoveVal(String k) {
//		return false;
//	}
	public void mapClean(String name) throws DaoException {
//		tableDrop(tableName)
		delete(MAP_TABLE_NAME(), 
			OMap(MAP_TABLE_COLUMN_NAME, name));
	}
	private void mapInit() throws DaoException {
		try {
			if(!this.tableExists(MAP_TABLE_NAME())) {
				this.tableCreate(MAP_TABLE_NAME(), Util.toOrderedMap(
					MAP_TABLE_COLUMN_NAME, TYPE_STRING,
					MAP_TABLE_COLUMN_KEY, TYPE_STRING, 
					MAP_TABLE_COLUMN_VALUE, TYPE_STRING_LONG
				));
			}
		} catch (Exception e) {
			throw new DaoException(e);
		}	
	}
		
	
}
